package com.dahuyou.tryy.too.simulate.interpreter.parse.clazz.classpath;

import com.dahuyou.tryy.too.simulate.interpreter.parse.clazz.classpath.entry.Entry;
import com.dahuyou.tryy.too.simulate.interpreter.parse.clazz.classpath.entry.impl.WildcardEntry;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * classpath类（jre entry+jre ext entry+应用entry）
 */
public class Classpath {
    // jre路径的entry（jvm中启动类加载器使用）
    private Entry bootstrapClasspath;
    // jre扩展路径entry（jvm中扩展类加载器使用）
    private Entry extensionClasspath;
    // 应用class路径entry（jvm中app类加载器使用）
    private Entry userClasspath;

    public Classpath(String jreOption, String cpOption) {
        //启动类(D:\programs\javas\java1.8\jre\lib)&扩展类(D:\programs\javas\java1.8\jre\lib\ext)
        bootstrapAndExtensionClasspath(jreOption);
        //用户类 d:\test\target\classes
        parseUserClasspath(cpOption);
    }

    private void bootstrapAndExtensionClasspath(String jreOption) {
        String jreDir = getJreDir(jreOption);

        //..jre/lib/* jre核心类库初始化
        String jreLibPath = Paths.get(jreDir, "lib") + File.separator + "*";
        bootstrapClasspath = new WildcardEntry(jreLibPath);

        //..jre/lib/ext/* jre ext初始化
        String jreExtPath = Paths.get(jreDir, "lib", "ext") + File.separator + "*";
        extensionClasspath = new WildcardEntry(jreExtPath);

    }

    private static String getJreDir(String jreOption) {
        // 用户直接设置了jre目录 D:\programs\javas\java1.8\jre
        if (jreOption != null && Files.exists(Paths.get(jreOption))) {
            return jreOption;
        }
        if (Files.exists(Paths.get("./jre"))) {
            return "./jre";
        }
        String jh = System.getenv("JAVA_HOME");
        if (jh != null) {
            return Paths.get(jh, "jre").toString();
        }
        throw new RuntimeException("Can not find JRE folder!");
    }

    private void parseUserClasspath(String cpOption) {
        if (cpOption == null) {
            cpOption = ".";
        }
        userClasspath = Entry.create(cpOption);
    }

    public byte[] readClass(String className) throws Exception {
        className = className + ".class";
        // 1：先使用jre 的entry加载（对应jvm先通过启动类加载器加载）
        try {
            return bootstrapClasspath.readClass(className);
        } catch (Exception ignored) {
            //ignored
        }
        // 2：jre的entry加载不到，使用ext对应的entry加载（对应jvm 启动类加载器加载不到，使用ext类加载器加载）
        try {
            return extensionClasspath.readClass(className);
        } catch (Exception ignored) {
            //ignored
        }
        // 3：最后通过用户类 entry加载（对应jvm最后猜使用app应用类加载器）
        return userClasspath.readClass(className);
    }

}
